home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 21 / AACD 21.iso / AACD / Programming / CVS / source / amiga / amiga.c < prev    next >
Encoding:
C/C++ Source or Header  |  2001-04-29  |  57.9 KB  |  2,793 lines

  1. /*
  2.  * $Id$
  3.  *
  4.  * :ts=4
  5.  *
  6.  * AmigaOS wrapper routines for GNU CVS, using the AmiTCP V3 API
  7.  * and the SAS/C V6.58 compiler.
  8.  *
  9.  * Written and adapted by Olaf `Olsen' Barthel <olsen@sourcery.han.de>
  10.  * adapted to cvs-1.11.1p1 by Jens Langner <Jens.Langner@htw-dresden.de>
  11.  *
  12.  * This program is free software; you can redistribute it and/or modify
  13.  * it under the terms of the GNU General Public License as published by
  14.  * the Free Software Foundation; either version 2 of the License, or
  15.  * (at your option) any later version.
  16.  *
  17.  * This program is distributed in the hope that it will be useful,
  18.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  19.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  20.  * GNU General Public License for more details.
  21.  *
  22.  * You should have received a copy of the GNU General Public License
  23.  * along with this program; if not, write to the Free Software
  24.  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  25.  */
  26.  
  27. #include <exec/memory.h>
  28.  
  29. #include <dos/dosextens.h>
  30. #include <dos/dostags.h>
  31.  
  32. #include <libraries/locale.h>
  33.  
  34. #include <bsdsocket/socketbasetags.h>
  35. #include <libraries/usergroup.h>
  36.  
  37. #include <clib/exec_protos.h>
  38. #include <clib/debug_protos.h>
  39. #include <clib/dos_protos.h>
  40. #include <clib/utility_protos.h>
  41. #include <clib/socket_protos.h>
  42. #include <clib/usergroup_protos.h>
  43. #include <clib/locale_protos.h>
  44. #include <clib/alib_protos.h>
  45.  
  46. #include <pragmas/exec_sysbase_pragmas.h>
  47. #include <pragmas/dos_pragmas.h>
  48. #include <pragmas/utility_pragmas.h>
  49. #include <pragmas/socket_pragmas.h>
  50. #include <pragmas/usergroup_pragmas.h>
  51. #include <pragmas/locale_pragmas.h>
  52.  
  53. #include <sys/types.h>
  54. #include <sys/socket.h>
  55. #include <sys/param.h>
  56. #include <sys/ioctl.h>
  57.  
  58. #include <constructor.h>
  59. #include <time.h>
  60. #include <utime.h>
  61. #include <stdio.h>
  62. #include <errno.h>
  63. #include <dirent.h>
  64. #include <netdb.h>
  65. #include <stat.h>
  66. #include <signal.h>
  67. #include <stdlib.h>
  68. #include <pwd.h>
  69. #include <grp.h>
  70. #include <dos.h>
  71.  
  72. #include <netinet/ip.h>
  73. #include <netinet/tcp.h>
  74.  
  75. #include <net/if.h>
  76. #include <unistd.h>
  77.  
  78. #include <ios1.h>
  79.  
  80. /****************************************************************************/
  81.  
  82. #include "_assert.h"
  83.  
  84. /****************************************************************************/
  85.  
  86. // global debug macros
  87. #define DEBUG_MAKRO_NOLF { kprintf("0x%08lx # "__FUNC__, (ULONG)FindTask(NULL)); }
  88. #define DEBUG_MAKRO_LF   { kprintf("\n", NULL); }
  89. #define DEBUG_MAKRO      { kprintf("0x%08lx # "__FUNC__"\n", (ULONG)FindTask(NULL)); }
  90.  
  91. /****************************************************************************/
  92.  
  93. #define const
  94. #define NO_NAME_REPLACEMENT
  95. #include "amiga.h"
  96. #include "error.h"
  97.  
  98. /****************************************************************************/
  99.  
  100. #define UNIX_TIME_OFFSET 252460800
  101.  
  102. /****************************************************************************/
  103.  
  104. #define ZERO    ((BPTR)NULL)
  105. #define SAME    (0)
  106. #define OK        (0)
  107. #define CANNOT    !
  108. #define NOT        !
  109.  
  110. /****************************************************************************/
  111.  
  112. /* This macro lets us long-align structures on the stack */
  113. #define D_S(type,name) \
  114.     char a_##name[sizeof(type)+3]; \
  115.     type *name = (type *)((LONG)(a_##name+3) & ~3)
  116.  
  117. /****************************************************************************/
  118.  
  119. #define NUM_ENTRIES(t)        (sizeof(t) / sizeof(t[0]))
  120.  
  121. /****************************************************************************/
  122.  
  123. #define FIB_IS_FILE(fib)    ((fib)->fib_DirEntryType < 0)
  124. #define FIB_IS_DRAWER(fib)    ((fib)->fib_DirEntryType >= 0 && \
  125.                              (fib)->fib_DirEntryType != ST_SOFTLINK && \
  126.                              (fib)->fib_DirEntryType != ST_LINKDIR)
  127.  
  128. /****************************************************************************/
  129.  
  130. #define FLAG_IS_SET(v,f)    (((v) & (f)) == (f))
  131. #define SET_FLAG(v,f)        (v |= (f))
  132.  
  133. /****************************************************************************/
  134.  
  135. extern void * xmalloc(size_t size);
  136. extern char * xstrdup(const char * const str);
  137.  
  138. /****************************************************************************/
  139.  
  140. extern struct Library * SysBase;
  141. extern struct Library * DOSBase;
  142. extern struct Library * UtilityBase;
  143.  
  144. /****************************************************************************/
  145.  
  146. static struct Library * SocketBase;
  147. static struct Library * UserGroupBase;
  148.  
  149. /****************************************************************************/
  150.  
  151. static struct Library * LocaleBase;
  152.  
  153. /****************************************************************************/
  154.  
  155. long __stack = 20000;
  156.  
  157. static    const char VersTag[] = "\0$VER: cvs 1.11.1p1 (29.04.2001) ported by Olaf Barthel and Jens Langner";
  158.  
  159. /****************************************************************************/
  160.  
  161. static void map_ioerr_to_errno(void);
  162. static int get_minutes_west(void);
  163. static void get_next_buffer(char **buffer_ptr);
  164. static void correct_name(char **name_ptr);
  165. static void dispatch(void);
  166. static void close_libs(void);
  167. static void initialize_libraries(void);
  168. static int recursive_unlink_file_dir(char *f);
  169. static int compare(char **a, char **b);
  170. static void convert_fileinfo_to_stat(struct FileInfoBlock *fib, struct stat *st);
  171. static void restore_home_dir(void);
  172. static int amiga_rcmd(char **remote_hostname, int remote_port, char *local_user, char *remote_user, char *command);
  173.  
  174. /****************************************************************************/
  175.  
  176. static void
  177. map_ioerr_to_errno(void)
  178. {
  179.     /* This routine maps AmigaDOS error codes to
  180.      * Unix error codes, as far as this is possible.
  181.      * This table contains AmigaDOS error codes
  182.      * the emulated routines won't generate. I have
  183.      * included them for the sake of completeness.
  184.      */
  185.     struct { LONG IoErr; int errno; } map_table[] =
  186.     {
  187.         ERROR_NO_FREE_STORE,            ENOMEM,
  188.         ERROR_TASK_TABLE_FULL,            ENOMEM,
  189.         ERROR_BAD_TEMPLATE,                EINVAL,
  190.         ERROR_BAD_NUMBER,                EINVAL,
  191.         ERROR_REQUIRED_ARG_MISSING,        EINVAL,
  192.         ERROR_KEY_NEEDS_ARG,            EINVAL,
  193.         ERROR_TOO_MANY_ARGS,            EINVAL,
  194.         ERROR_UNMATCHED_QUOTES,            EINVAL,
  195.         ERROR_LINE_TOO_LONG,            ENAMETOOLONG,
  196.         ERROR_FILE_NOT_OBJECT,            ENOEXEC,
  197.         ERROR_INVALID_RESIDENT_LIBRARY,    EIO,
  198.         ERROR_NO_DEFAULT_DIR,            EIO,
  199.         ERROR_OBJECT_IN_USE,            EBUSY,
  200.         ERROR_OBJECT_EXISTS,            EEXIST,
  201.         ERROR_DIR_NOT_FOUND,            ENOENT,
  202.         ERROR_OBJECT_NOT_FOUND,            ENOENT,
  203.         ERROR_BAD_STREAM_NAME,            EINVAL,
  204.         ERROR_OBJECT_TOO_LARGE,            EFBIG,
  205.         ERROR_ACTION_NOT_KNOWN,            ENOSYS,
  206.         ERROR_INVALID_COMPONENT_NAME,    EINVAL,
  207.         ERROR_INVALID_LOCK,                EBADF,
  208.         ERROR_OBJECT_WRONG_TYPE,        EFTYPE,
  209.         ERROR_DISK_NOT_VALIDATED,        EROFS,
  210.         ERROR_DISK_WRITE_PROTECTED,        EROFS,
  211.         ERROR_RENAME_ACROSS_DEVICES,    EXDEV,
  212.         ERROR_DIRECTORY_NOT_EMPTY,        ENOTEMPTY,
  213.         ERROR_TOO_MANY_LEVELS,            ENAMETOOLONG,
  214.         ERROR_DEVICE_NOT_MOUNTED,        ENXIO,
  215.         ERROR_SEEK_ERROR,                EIO,
  216.         ERROR_COMMENT_TOO_BIG,            ENAMETOOLONG,
  217.         ERROR_DISK_FULL,                ENOSPC,
  218.         ERROR_DELETE_PROTECTED,            EACCES,
  219.         ERROR_WRITE_PROTECTED,            EACCES,
  220.         ERROR_READ_PROTECTED,            EACCES,
  221.         ERROR_NOT_A_DOS_DISK,            EFTYPE,
  222.         ERROR_NO_DISK,                    EACCES,
  223.         ERROR_NO_MORE_ENTRIES,            EIO,
  224.         ERROR_IS_SOFT_LINK,                EFTYPE,
  225.         ERROR_OBJECT_LINKED,            EIO,
  226.         ERROR_BAD_HUNK,                    ENOEXEC,
  227.         ERROR_NOT_IMPLEMENTED,            ENOSYS,
  228.         ERROR_RECORD_NOT_LOCKED,        EIO,
  229.         ERROR_LOCK_COLLISION,            EACCES,
  230.         ERROR_LOCK_TIMEOUT,                EIO,
  231.         ERROR_UNLOCK_ERROR,                EIO,
  232.         ERROR_BUFFER_OVERFLOW,            EIO,
  233.         ERROR_BREAK,                    EINTR,
  234.         ERROR_NOT_EXECUTABLE,            ENOEXEC
  235.     };
  236.  
  237.     LONG Error = IoErr();
  238.  
  239.     if(Error != OK)
  240.     {
  241.         int i;
  242.  
  243.         /* If nothing else matches, we can always
  244.          * flag it as an I/O error.
  245.          */
  246.         errno = EIO;
  247.  
  248.         for(i = 0 ; i < NUM_ENTRIES(map_table) ; i++)
  249.         {
  250.             if(map_table[i].IoErr == Error)
  251.             {
  252.                 errno = map_table[i].errno;
  253.                 break;
  254.             }
  255.         }
  256.     }
  257. }
  258.  
  259. /****************************************************************************/
  260.  
  261. static int
  262. get_minutes_west(void)
  263. {
  264.     int minutes_west;
  265.  
  266.     if(LocaleBase == NULL)
  267.         LocaleBase = OpenLibrary("locale.library",38);
  268.  
  269.     if(LocaleBase != NULL)
  270.     {
  271.         struct Locale * loc;
  272.  
  273.         loc = OpenLocale(NULL);
  274.  
  275.         minutes_west = loc->loc_GMTOffset;
  276.  
  277.         CloseLocale(loc);
  278.     }
  279.     else
  280.     {
  281.         minutes_west = 0;
  282.     }
  283.  
  284.     return(minutes_west);
  285. }
  286.  
  287. /****************************************************************************/
  288.  
  289. #define MAX_FILENAME_LEN 1024
  290.  
  291. static void
  292. get_next_buffer(char ** buffer_ptr)
  293. {
  294.     static char buffer_slots[8][MAX_FILENAME_LEN];
  295.     static int buffer_index;
  296.  
  297.     (*buffer_ptr) = buffer_slots[buffer_index];
  298.     buffer_index = (buffer_index + 1) % 8;
  299. }
  300.  
  301. /****************************************************************************/
  302.  
  303. static void
  304. correct_name(char ** name_ptr)
  305. {
  306.     char * buffer;
  307.     int len,i;
  308.     char * name;
  309.  
  310.     ENTER();
  311.  
  312.     name = (*name_ptr);
  313.     if(name[0] == '/')
  314.     {
  315.         BOOL done;
  316.  
  317.         SHOWSTRING(name);
  318.  
  319.         get_next_buffer(&buffer);
  320.  
  321.         done = FALSE;
  322.  
  323.         len = strlen(name);
  324.         for(i = 1 ; i <= len ; i++)
  325.         {
  326.             if(name[i] == '/' || name[i] == '\0')
  327.             {
  328.                 memcpy(buffer,name+1,i-1);
  329.                 buffer[i-1] = ':';
  330.                 strcpy(&buffer[i],&name[i+1]);
  331.                 done = TRUE;
  332.                 break;
  333.             }
  334.         }
  335.  
  336.         if(NOT done)
  337.             strcpy(buffer,name);
  338.  
  339.         SHOWSTRING(buffer);
  340.  
  341.         name = buffer;
  342.     }
  343.     else
  344.     {
  345.         len = strlen(name);
  346.  
  347.         SHOWSTRING(name);
  348.  
  349.         for(i = 0 ; i < len-1 ; i++)
  350.         {
  351.             if(name[i] == ':' && name[i+1] == '/')
  352.             {
  353.                 get_next_buffer(&buffer);
  354.  
  355.                 memcpy(buffer,name,i+1);
  356.                 strcpy(&buffer[i+1],&name[i+2]);
  357.  
  358.                 SHOWSTRING(buffer);
  359.  
  360.                 name = buffer;
  361.                 break;
  362.             }
  363.         }
  364.     }
  365.  
  366.     if(strncmp(name,"./",2) == SAME)
  367.     {
  368.         get_next_buffer(&buffer);
  369.  
  370.         strcpy(buffer,name+2);
  371.         name = buffer;
  372.     }
  373.     else if (strncmp(name,"../",3) == SAME)
  374.     {
  375.         get_next_buffer(&buffer);
  376.  
  377.         strcpy(buffer,name+3);
  378.         name = buffer;
  379.     }
  380.     else if (strcmp(name,".") == SAME)
  381.     {
  382.         get_next_buffer(&buffer);
  383.  
  384.         strcpy(buffer,"");
  385.         name = buffer;
  386.     }
  387.     else if (strcmp(name,"..") == SAME)
  388.     {
  389.         get_next_buffer(&buffer);
  390.  
  391.         strcpy(buffer,"/");
  392.         name = buffer;
  393.     }
  394.  
  395.     len = strlen(name);
  396.     if(len > 0 && name[len-1] == '/')
  397.         name[--len] = '\0';
  398.  
  399.     (*name_ptr) = name;
  400.  
  401.     LEAVE();
  402. }
  403.  
  404. /****************************************************************************/
  405.  
  406. void *
  407. amiga_valloc(size_t bytes)
  408. {
  409.     void * result;
  410.  
  411.     ENTER();
  412.     SHOWVALUE(bytes);
  413.  
  414.     result = malloc(bytes);
  415.  
  416.     RETURN(result);
  417.     return(result);
  418. }
  419.  
  420. /****************************************************************************/
  421.  
  422. int
  423. amiga_symlink(char *to,char *from)
  424. {
  425.     int result;
  426.  
  427.     ENTER();
  428.  
  429.     SHOWSTRING(to);
  430.     SHOWSTRING(from);
  431.  
  432.     result = -1;
  433.     errno = EINVAL;
  434.  
  435.     RETURN(result);
  436.     return(result);
  437. }
  438.  
  439. /****************************************************************************/
  440.  
  441. int
  442. amiga_readlink(char *path,char *buf,int buf_size)
  443. {
  444.     int result;
  445.  
  446.     ENTER();
  447.  
  448.     SHOWSTRING(path);
  449.  
  450.     result = -1;
  451.     errno = EINVAL;
  452.  
  453.     RETURN(result);
  454.     return(result);
  455. }
  456.  
  457. /****************************************************************************/
  458.  
  459. unsigned
  460. amiga_sleep(unsigned seconds)
  461. {
  462.     Delay(TICKS_PER_SECOND * seconds);
  463.  
  464.     return(0);
  465. }
  466.  
  467. /****************************************************************************/
  468.  
  469. unsigned long
  470. amiga_umask(unsigned long mask)
  471. {
  472.     return(umask(mask));
  473. }
  474.  
  475. /****************************************************************************/
  476.  
  477. unsigned long
  478. amiga_waitpid(unsigned long pid,int *stat_loc,int options)
  479. {
  480.     return(0);
  481. }
  482.  
  483. /****************************************************************************/
  484.  
  485. int
  486. amiga_utime(char *name,struct utimbuf *time)
  487. {
  488.     struct DateStamp ds;
  489.     int result = -1;
  490.  
  491.     ENTER();
  492.  
  493.     correct_name(&name);
  494.  
  495.     SHOWSTRING(name);
  496.  
  497.     /* Use the current time? */
  498.     if(time == NULL)
  499.     {
  500.         DateStamp(&ds);
  501.     }
  502.     else
  503.     {
  504.         int minutes_west = get_minutes_west();
  505.         ULONG seconds;
  506.  
  507.         /* Convert the time given. */
  508.         if(time->modtime < (UNIX_TIME_OFFSET + 60 * minutes_west))
  509.             seconds = 0;
  510.         else
  511.             seconds = time->modtime - (UNIX_TIME_OFFSET + 60 * minutes_west);    /* translate from UTC to local time */
  512.  
  513.         ds.ds_Days        = (seconds / (24*60*60));
  514.         ds.ds_Minute    = (seconds % (24*60*60)) / 60;
  515.         ds.ds_Tick        = (seconds               % 60) * TICKS_PER_SECOND;
  516.     }
  517.  
  518.     if(SetFileDate((STRPTR)name,&ds))
  519.         result = 0;
  520.  
  521.     RETURN(result);
  522.     return(result);
  523. }
  524.  
  525. /****************************************************************************/
  526.  
  527. int
  528. amiga_geteuid(void)
  529. {
  530.     return(0);
  531. }
  532.  
  533. /****************************************************************************/
  534.  
  535. int
  536. amiga_getuid(void)
  537. {
  538.     return(getuid());
  539. }
  540.  
  541. /****************************************************************************/
  542.  
  543. int
  544. amiga_getgid(void)
  545. {
  546.     return(getgid());
  547. }
  548.  
  549. /****************************************************************************/
  550.  
  551. long amiga_getgroups(long gidsetlen, long *gidset)
  552. {
  553.     return(getgroups(gidsetlen, gidset));
  554. }
  555.  
  556. /****************************************************************************/
  557.  
  558. long
  559. amiga_getpid(void)
  560. {
  561.     static long old_pid = -1;
  562.     long result;
  563.  
  564.     ENTER();
  565.  
  566.     if(old_pid == -1)
  567.     {
  568.         struct Process * this_process;
  569.         LONG max_cli;
  570.         LONG which;
  571.         LONG i;
  572.  
  573.         this_process = (struct Process *)FindTask(NULL);
  574.  
  575.         Forbid();
  576.  
  577.         which = max_cli = MaxCli();
  578.  
  579.         for(i = 1 ; i <= max_cli ; i++)
  580.         {
  581.             if(FindCliProc(i) == this_process)
  582.             {
  583.                 which = i;
  584.                 break;
  585.             }
  586.         }
  587.  
  588.         Permit();
  589.  
  590.         old_pid = which;
  591.     }
  592.  
  593.     result = old_pid;
  594.  
  595.     RETURN(result);
  596.     return(result);
  597. }
  598.  
  599. /****************************************************************************/
  600.  
  601. char *
  602. amiga_getlogin(void)
  603. {
  604.     static char name[256];
  605.     int i;
  606.  
  607.     ENTER();
  608.  
  609.     if(GetVar("USER",name,sizeof(name),0) <= 0)
  610.     {
  611.         if(GetVar("LOGUSER",name,sizeof(name),0) <= 0)
  612.         {
  613.             if(GetVar("USERNAME",name,sizeof(name),0) <= 0)
  614.                 strcpy(name,"anonymous");
  615.         }
  616.     }
  617.  
  618.     for(i = strlen(name)-1 ; i >= 0 ; i--)
  619.     {
  620.         if(name[i] == ' ' || name[i] == '\t' || name[i] == '\r' || name[i] == '\n')
  621.             name[i] = '\0';
  622.         else
  623.             break;
  624.     }
  625.  
  626.     SHOWSTRING(name);
  627.  
  628.     RETURN(name);
  629.     return(name);
  630. }
  631.  
  632. /****************************************************************************/
  633.  
  634. struct passwd *
  635. amiga_getpwuid(int uid)
  636. {
  637.     static struct passwd pw;
  638.  
  639.     ENTER();
  640.  
  641.     SHOWVALUE(uid);
  642.  
  643.     memset(&pw,0,sizeof(pw));
  644.  
  645.     pw.pw_dir    = "CVSHOME:";        /* pseudo-home directory */
  646.     pw.pw_gid    = 1;                /* ZZZ wrong */
  647.     pw.pw_name    = amiga_getlogin();
  648.     pw.pw_uid    = uid;                /* ZZZ wrong */
  649.  
  650.     RETURN(&pw);
  651.     return(&pw);
  652. }
  653.  
  654. /****************************************************************************/
  655.  
  656. struct passwd *
  657. amiga_getpwnam(char *name)
  658. {
  659.     struct passwd * result;
  660.  
  661.     ENTER();
  662.  
  663.     SHOWSTRING(name);
  664.  
  665.     result = amiga_getpwuid(1);
  666.  
  667.     RETURN(result);
  668.     return(result);
  669. }
  670.  
  671. /****************************************************************************/
  672.  
  673. struct group *
  674. amiga_getgrnam(char *name)
  675. {
  676.     struct group * result;
  677.  
  678.     ENTER();
  679.  
  680.     result = NULL;
  681.  
  682.     RETURN(result);
  683.     return(result);
  684. }
  685.  
  686. /****************************************************************************/
  687.  
  688. char *
  689. amiga_getpass(const char *prompt)
  690. {
  691.     struct UFB * ufb;
  692.     char * result = NULL;
  693.  
  694.     ENTER();
  695.  
  696.     SHOWSTRING(prompt);
  697.  
  698.     ufb = chkufb(fileno(stdin));
  699.     if(ufb != NULL)
  700.     {
  701.         void (*old_sig_handler)(int);
  702.  
  703.         old_sig_handler = signal(SIGINT,SIG_IGN);
  704.  
  705.         if(SetMode(ufb->ufbfh,DOSTRUE))
  706.         {
  707.             static char pwd_buf[128];
  708.             int len,c;
  709.  
  710.             fputs(prompt, stderr);
  711.             fflush(stderr);
  712.  
  713.             len = 0;
  714.             while(TRUE)
  715.             {
  716.                 c = -1;
  717.  
  718.                 while(TRUE)
  719.                 {
  720.                     if(CheckSignal(SIGBREAKF_CTRL_C))
  721.                     {
  722.                         SetMode(ufb->ufbfh,DOSFALSE);
  723.                         signal(SIGINT,old_sig_handler);
  724.  
  725.                         raise(SIGINT);
  726.  
  727.                         signal(SIGINT,SIG_IGN);
  728.                         SetMode(ufb->ufbfh,DOSTRUE);
  729.                     }
  730.  
  731.                     if(WaitForChar(ufb->ufbfh,TICKS_PER_SECOND / 2))
  732.                     {
  733.                         c = fgetc(stdin);
  734.                         if(c == '\003')
  735.                         {
  736.                             SetMode(ufb->ufbfh,DOSFALSE);
  737.                             signal(SIGINT,old_sig_handler);
  738.  
  739.                             raise(SIGINT);
  740.  
  741.                             signal(SIGINT,SIG_IGN);
  742.                             SetMode(ufb->ufbfh,DOSTRUE);
  743.                         }
  744.                         else
  745.                         {
  746.                             break;
  747.                         }
  748.                     }
  749.                 }
  750.  
  751.                 if(c == '\r' || c == '\n')
  752.                     break;
  753.  
  754.                 if(((c >= ' ' && c < 127) || (c >= 160)) && len < sizeof(pwd_buf)-1)
  755.                 {
  756.                     pwd_buf[len++] = c;
  757.                     pwd_buf[len] = '\0';
  758.                 }
  759.             }
  760.  
  761.             SetMode(ufb->ufbfh,DOSFALSE);
  762.  
  763.             fputs("\n",stderr);
  764.  
  765.             SHOWSTRING(pwd_buf);
  766.  
  767.             result = pwd_buf;
  768.         }
  769.  
  770.         signal(SIGINT,old_sig_handler);
  771.     }
  772.  
  773.     RETURN(result);
  774.     return(result);
  775. }
  776.  
  777. /****************************************************************************/
  778.  
  779. int
  780. amiga_gethostname(char * name,int namelen)
  781. {
  782.     static char hostname[256];
  783.     int i,len;
  784.  
  785.     ENTER();
  786.  
  787.     if(GetVar("HOST",hostname,sizeof(hostname),0) <= 0)
  788.     {
  789.         if(GetVar("HOSTNAME",hostname,sizeof(hostname),0) <= 0)
  790.             strcpy(hostname,"anonymous");
  791.     }
  792.  
  793.     for(i = strlen(hostname)-1 ; i >= 0 ; i--)
  794.     {
  795.         if(hostname[i] == ' ' || hostname[i] == '\t' || hostname[i] == '\r' || hostname[i] == '\n')
  796.             hostname[i] = '\0';
  797.         else
  798.             break;
  799.     }
  800.  
  801.     len = strlen(hostname);
  802.     if(len > namelen)
  803.         len = namelen;
  804.  
  805.     memcpy(name,hostname,len);
  806.     name[len] = '\0';
  807.  
  808.     SHOWSTRING(name);
  809.  
  810.     RETURN(0);
  811.     return(0);
  812. }
  813.  
  814. /****************************************************************************/
  815.  
  816. int
  817. amiga_pclose(FILE * pipe)
  818. {
  819.     ENTER();
  820.  
  821.     fclose(pipe);
  822.  
  823.     RETURN(0);
  824.     return(0);
  825. }
  826.  
  827. /****************************************************************************/
  828.  
  829. FILE *
  830. amiga_popen(char * command, const char * mode)
  831. {
  832.     FILE * result = NULL;
  833.     char temp_name[40];
  834.     BPTR output;
  835.  
  836.     ENTER();
  837.  
  838.     correct_name(&command);
  839.  
  840.     SHOWSTRING(command);
  841.     SHOWSTRING(mode);
  842.  
  843.     sprintf(temp_name,"PIPE:%08x.%08x",FindTask(NULL),time(NULL));
  844.  
  845.     output = Open(temp_name,MODE_NEWFILE);
  846.     if(output != ZERO)
  847.     {
  848.         LONG res;
  849.  
  850.         res = SystemTags(command,
  851.             SYS_Input,        Input(),
  852.             SYS_Output,        output,
  853.             SYS_Asynch,        TRUE,
  854.             SYS_UserShell,    TRUE,
  855.             NP_CloseInput,    FALSE,
  856.         TAG_END);
  857.  
  858.         switch(res)
  859.         {
  860.             case 0:
  861.                 result = fopen(temp_name,mode);
  862.                 break;
  863.  
  864.             case -1:
  865.                 errno = ENOMEM;
  866.                 Close(output);
  867.                 break;
  868.  
  869.             default:
  870.                 errno = EIO;
  871.                 break;
  872.         }
  873.     }
  874.     else
  875.     {
  876.         errno = EIO;
  877.     }
  878.  
  879.     RETURN(result);
  880.     return(result);
  881. }
  882.  
  883. /****************************************************************************/
  884.  
  885. static struct MsgPort magic_port;
  886.  
  887. /****************************************************************************/
  888.  
  889. #define ACTION_LOCATE_SOCKET    2050    /* arg1=domain, arg2=type, arg3=protocol -> lock (BPTR) */
  890. #define ACTION_COPY_DIR_SOCKET    2051    /* arg1=socket -> lock (BPTR) */
  891.  
  892. /****************************************************************************/
  893.  
  894. static void
  895. dispatch(void)
  896. {
  897.     struct FileHandle * fh;
  898.     struct FileLock * fl;
  899.     long fd;
  900.     struct DosPacket * dp;
  901.     struct Message * mn;
  902.     LONG res1,res2;
  903.  
  904.     ENTER();
  905.  
  906.     /* We arrive here with interrupt processing disabled. We don't need
  907.      * that and we certainly don't want that either.
  908.      */
  909.     Enable();
  910.  
  911.     /* There's always just one message waiting. */
  912.     mn = GetMsg(&magic_port);
  913.  
  914.     dp = (struct DosPacket *)mn->mn_Node.ln_Name;
  915.  
  916.     res1 = DOSFALSE;
  917.     res2 = 0;
  918.  
  919.     switch(dp->dp_Action)
  920.     {
  921.         case ACTION_FREE_LOCK: /* lock -> bool */
  922.  
  923.             SHOWMSG("ACTION_FREE_LOCK");
  924.  
  925.             fl = BADDR(dp->dp_Arg1);
  926.  
  927.             if(SocketBase != NULL)
  928.                 CloseSocket(fl->fl_Key);
  929.  
  930.             res1 = DOSTRUE;
  931.  
  932.             break;
  933.  
  934.         case ACTION_READ: /* socket,buffer (APTR),length -> length */
  935.  
  936.             SHOWMSG("ACTION_READ");
  937.             SHOWVALUE(dp->dp_Arg3);
  938.  
  939.             if(SocketBase != NULL)
  940.                 res1 = recv(dp->dp_Arg1,(APTR)dp->dp_Arg2,dp->dp_Arg3,0);
  941.  
  942.             break;
  943.  
  944.         case ACTION_WRITE: /* socket,buffer (APTR),length -> length */
  945.  
  946.             SHOWMSG("ACTION_WRITE");
  947.             SHOWVALUE(dp->dp_Arg3);
  948.  
  949.             if(SocketBase != NULL)
  950.                 res1 = send(dp->dp_Arg1,(APTR)dp->dp_Arg2,dp->dp_Arg3,0);
  951.  
  952.             break;
  953.  
  954.         case ACTION_END: /* socket -> bool */
  955.  
  956.             SHOWMSG("ACTION_END");
  957.  
  958.             if(SocketBase != NULL)
  959.                 CloseSocket(dp->dp_Arg1);
  960.  
  961.             res1 = DOSTRUE;
  962.  
  963.             break;
  964.  
  965.         case ACTION_FH_FROM_LOCK: /* file handle (BPTR), lock (BPTR) -> bool */
  966.  
  967.             SHOWMSG("ACTION_FH_FROM_LOCK");
  968.  
  969.             fh = BADDR(dp->dp_Arg1);
  970.             fl = BADDR(dp->dp_Arg2);
  971.  
  972.             fh->fh_Arg1 = fl->fl_Key;
  973.  
  974.             FreeVec(fl);
  975.  
  976.             res1 = DOSTRUE;
  977.  
  978.             break;
  979.  
  980.         case ACTION_LOCATE_SOCKET: /* domain, type, protocol -> lock (BPTR) */
  981.  
  982.             SHOWMSG("ACTION_LOCATE_SOCKET");
  983.  
  984.             if(SocketBase != NULL)
  985.                 fd = socket(dp->dp_Arg1,dp->dp_Arg2,dp->dp_Arg3);
  986.             else
  987.                 fd = -1;
  988.  
  989.             if(fd < 0)
  990.             {
  991.                 res2 = ERROR_NO_FREE_STORE;
  992.                 break;
  993.             }
  994.  
  995.             fl = AllocVec(sizeof(*fl),MEMF_ANY|MEMF_PUBLIC|MEMF_CLEAR);
  996.             if(fl == NULL)
  997.             {
  998.                 CloseSocket(fd);
  999.                 res2 = ERROR_NO_FREE_STORE;
  1000.                 break;
  1001.             }
  1002.  
  1003.             fl->fl_Key        = fd;
  1004.             fl->fl_Access    = SHARED_LOCK;
  1005.             fl->fl_Task        = &magic_port;
  1006.  
  1007.             res1 = MKBADDR(fl);
  1008.  
  1009.             break;
  1010.  
  1011.         case ACTION_COPY_DIR_SOCKET: /* socket -> lock (BPTR) */
  1012.  
  1013.             SHOWMSG("ACTION_COPY_DIR_SOCKET");
  1014.  
  1015.             if(SocketBase != NULL)
  1016.                 fd = Dup2Socket(dp->dp_Arg1,-1);
  1017.             else
  1018.                 fd = -1;
  1019.  
  1020.             if(fd < 0)
  1021.             {
  1022.                 res2 = ERROR_NO_FREE_STORE;
  1023.                 break;
  1024.             }
  1025.  
  1026.             fl = AllocVec(sizeof(*fl),MEMF_ANY|MEMF_PUBLIC|MEMF_CLEAR);
  1027.             if(fl == NULL)
  1028.             {
  1029.                 CloseSocket(fd);
  1030.                 res2 = ERROR_NO_FREE_STORE;
  1031.                 break;
  1032.             }
  1033.  
  1034.             fl->fl_Key        = fd;
  1035.             fl->fl_Access    = SHARED_LOCK;
  1036.             fl->fl_Task        = &magic_port;
  1037.  
  1038.             res1 = MKBADDR(fl);
  1039.  
  1040.             break;
  1041.  
  1042.         default:
  1043.  
  1044.             D(("ACTION_??? (type=%ld)",dp->dp_Action));
  1045.  
  1046.             res2 = ERROR_ACTION_NOT_KNOWN;
  1047.             break;
  1048.     }
  1049.  
  1050.     SHOWVALUE(res1);
  1051.     SHOWVALUE(res2);
  1052.  
  1053.     ReplyPkt(dp,res1,res2);
  1054.  
  1055.     /* Return to the entry state, that is with interrupts disabled
  1056.      * since PutMsg() will turn them back on before it returns.
  1057.      */
  1058.     Disable();
  1059.  
  1060.     LEAVE();
  1061. }
  1062.  
  1063. /****************************************************************************/
  1064.  
  1065. static void
  1066. close_libs(void)
  1067. {
  1068.     if(LocaleBase != NULL)
  1069.     {
  1070.         CloseLibrary(LocaleBase);
  1071.         LocaleBase = NULL;
  1072.     }
  1073.  
  1074.     if(SocketBase != NULL)
  1075.     {
  1076.         CloseLibrary(SocketBase);
  1077.         SocketBase = NULL;
  1078.     }
  1079.  
  1080.     if(UserGroupBase != NULL)
  1081.     {
  1082.         CloseLibrary(UserGroupBase);
  1083.         UserGroupBase = NULL;
  1084.     }
  1085. }
  1086.  
  1087. CBMLIB_DESTRUCTOR(close_libs)
  1088. {
  1089.     ENTER();
  1090.  
  1091.     close_libs();
  1092.  
  1093.     LEAVE();
  1094. }
  1095.  
  1096. /****************************************************************************/
  1097.  
  1098. CBMLIB_CONSTRUCTOR(init_magic_port)
  1099. {
  1100.     ENTER();
  1101.  
  1102.     /* Don't try this at home kids! We're all trained professionals here. */
  1103.     magic_port.mp_Flags    = 3;
  1104.     magic_port.mp_SigTask = (APTR)dispatch;
  1105.     NewList(&magic_port.mp_MsgList);
  1106.  
  1107.     RETURN(0);
  1108.     return(0);
  1109. }
  1110.  
  1111. /****************************************************************************/
  1112.  
  1113. static void
  1114. initialize_libraries(void)
  1115. {
  1116.     ENTER();
  1117.  
  1118.     if(SocketBase == NULL && UserGroupBase == NULL)
  1119.     {
  1120.         SocketBase = OpenLibrary("bsdsocket.library",3);
  1121.         if(SocketBase != NULL)
  1122.         {
  1123.             extern STRPTR _ProgramName;
  1124.  
  1125.             if(SocketBaseTags(
  1126.                 SBTM_SETVAL(SBTC_ERRNOPTR(sizeof(errno))),    &errno,
  1127.                 SBTM_SETVAL(SBTC_LOGTAGPTR),                _ProgramName,
  1128.             TAG_END) != 0)
  1129.             {
  1130.                 CloseLibrary(SocketBase);
  1131.                 SocketBase = NULL;
  1132.             }
  1133.         }
  1134.  
  1135.         UserGroupBase = OpenLibrary("usergroup.library",1);
  1136.         if(UserGroupBase != NULL)
  1137.         {
  1138.             if(ug_SetupContextTags(_ProgramName,
  1139.                 UGT_ERRNOPTR(sizeof(errno)),&errno,
  1140.             TAG_END) != 0)
  1141.             {
  1142.                 CloseLibrary(UserGroupBase);
  1143.                 UserGroupBase = NULL;
  1144.             }
  1145.         }
  1146.  
  1147.         if(SocketBase == NULL)
  1148.         {
  1149.             fprintf(stderr,"Could not open 'bsdsocket.library' V3; TCP/IP stack not running?\n");
  1150.             exit(RETURN_FAIL);
  1151.         }
  1152.         else if (UserGroupBase == NULL)
  1153.         {
  1154.             fprintf(stderr,"Could not open 'usergroup.library' V1; TCP/IP stack not running?\n");
  1155.             exit(RETURN_FAIL);
  1156.         }
  1157.     }
  1158.  
  1159.     LEAVE();
  1160. }
  1161.  
  1162. /****************************************************************************/
  1163.  
  1164. void __regargs
  1165. __chkabort(void)
  1166. {
  1167.     if(SetSignal(0,0) & SIGBREAKF_CTRL_C)
  1168.         raise(SIGINT);
  1169. }
  1170.  
  1171. void __regargs
  1172. _CXBRK(void)
  1173. {
  1174.     extern STRPTR _ProgramName;
  1175.  
  1176.     /* Flush the standard output streams so that
  1177.      * any following output will be printed after
  1178.      * any buffered stdio output.
  1179.      */
  1180.     if(WBenchMsg == NULL)
  1181.     {
  1182.         /* Don't let anybody stop us. */
  1183.         signal(SIGINT,SIG_IGN);
  1184.         signal(SIGTERM,SIG_IGN);
  1185.  
  1186.         fflush(stdout);
  1187.         fflush(stderr);
  1188.     }
  1189.  
  1190.     /* This routine is called when the program is interrupted. */
  1191.     if(DOSBase->lib_Version >= 37)
  1192.     {
  1193.         PrintFault(ERROR_BREAK,_ProgramName);
  1194.     }
  1195.     else
  1196.     {
  1197.         const char *famousLastWords = ": *** Break";
  1198.         BPTR output = Output();
  1199.  
  1200.         Write(output,(APTR)famousLastWords,strlen(famousLastWords));
  1201.         Write(output,_ProgramName,strlen(_ProgramName));
  1202.         Write(output,"\n",1);
  1203.     }
  1204.  
  1205.     restore_home_dir();
  1206.     close_libs();
  1207.  
  1208.     exit(RETURN_WARN);
  1209. }
  1210.  
  1211. /****************************************************************************/
  1212.  
  1213. char *
  1214. amiga_strerror(int code)
  1215. {
  1216.     char * result;
  1217.  
  1218.     ENTER();
  1219.  
  1220.     if(SocketBase != NULL)
  1221.     {
  1222.         struct TagItem tags[2];
  1223.  
  1224.         tags[0].ti_Tag    = SBTM_GETVAL(SBTC_ERRNOSTRPTR);
  1225.         tags[0].ti_Data    = code;
  1226.         tags[1].ti_Tag    = TAG_END;
  1227.  
  1228.         SocketBaseTagList(tags);
  1229.  
  1230.         result = (char *)tags[0].ti_Data;
  1231.     }
  1232.     else
  1233.     {
  1234.         result = strerror(code);
  1235.     }
  1236.  
  1237.     SHOWSTRING(result);
  1238.  
  1239.     RETURN(result);
  1240.     return(result);
  1241. }
  1242.  
  1243. /****************************************************************************/
  1244.  
  1245. int
  1246. amiga_mkdir(char *name,int mode)
  1247. {
  1248.     int result = OK;
  1249.     BPTR lock;
  1250.  
  1251.     ENTER();
  1252.  
  1253.     correct_name(&name);
  1254.  
  1255.     SHOWSTRING(name);
  1256.  
  1257.     lock = CreateDir(name);
  1258.     if(lock != ZERO)
  1259.     {
  1260.         UnLock(lock);
  1261.  
  1262.         amiga_chmod(name,mode);
  1263.     }
  1264.     else
  1265.     {
  1266.         LONG error = IoErr();
  1267.  
  1268.         if(error != ERROR_OBJECT_IN_USE)
  1269.         {
  1270.             SetIoErr(error);
  1271.  
  1272.             map_ioerr_to_errno();
  1273.  
  1274.             result = -1;
  1275.         }
  1276.     }
  1277.  
  1278.     RETURN(result);
  1279.     return(result);
  1280. }
  1281.  
  1282. /****************************************************************************/
  1283.  
  1284. struct hostent *
  1285. amiga_gethostbyname(char *name)
  1286. {
  1287.     struct hostent *result;
  1288.  
  1289.     ENTER();
  1290.     SHOWSTRING(name);
  1291.  
  1292.     initialize_libraries();
  1293.  
  1294.     result = gethostbyname(name);
  1295.  
  1296.     RETURN(result);
  1297.     return(result);
  1298. }
  1299.  
  1300. struct servent *
  1301. amiga_getservbyname(char *name,char *proto)
  1302. {
  1303.     struct servent *result;
  1304.  
  1305.     ENTER();
  1306.  
  1307.     SHOWSTRING(name);
  1308.     SHOWSTRING(proto);
  1309.  
  1310.     initialize_libraries();
  1311.  
  1312.     result = getservbyname(name,proto);
  1313.  
  1314.     RETURN(result);
  1315.     return(result);
  1316. }
  1317.  
  1318. /****************************************************************************/
  1319.  
  1320. int
  1321. amiga_bind(int fd,struct sockaddr *name,int namelen)
  1322. {
  1323.     struct FileHandle * fh;
  1324.     struct UFB * ufb;
  1325.     int result = -1;
  1326.  
  1327.     ENTER();
  1328.  
  1329.     initialize_libraries();
  1330.  
  1331.     ufb = chkufb(fd);
  1332.     if(ufb == NULL)
  1333.     {
  1334.         errno = EIO;
  1335.         goto out;
  1336.     }
  1337.  
  1338.     fh = (struct FileHandle *)BADDR(ufb->ufbfh);
  1339.     if(fh->fh_Type != &magic_port)
  1340.     {
  1341.         errno = EBADF;
  1342.         goto out;
  1343.     }
  1344.  
  1345.     result = bind(fh->fh_Arg1,name,namelen);
  1346.  
  1347.  out:
  1348.  
  1349.     RETURN(result);
  1350.     return(result);
  1351. }
  1352.  
  1353. int
  1354. amiga_connect(int fd,struct sockaddr *name,int namelen)
  1355. {
  1356.     struct FileHandle * fh;
  1357.     struct UFB * ufb;
  1358.     int result = -1;
  1359.  
  1360.     ENTER();
  1361.  
  1362.     initialize_libraries();
  1363.  
  1364.     ufb = chkufb(fd);
  1365.     if(ufb == NULL)
  1366.     {
  1367.         errno = EIO;
  1368.         goto out;
  1369.     }
  1370.  
  1371.     fh = (struct FileHandle *)BADDR(ufb->ufbfh);
  1372.     if(fh->fh_Type != &magic_port)
  1373.     {
  1374.         errno = EBADF;
  1375.         goto out;
  1376.     }
  1377.  
  1378.     result = connect(fh->fh_Arg1,name,namelen);
  1379.  
  1380.  out:
  1381.  
  1382.     RETURN(result);
  1383.     return(result);
  1384. }
  1385.  
  1386. int
  1387. amiga_dup(int socketfd)
  1388. {
  1389.     struct FileHandle * fh;
  1390.     BPTR socket_lock = ZERO;
  1391.     BPTR socket_handle = ZERO;
  1392.     int fd = -1;
  1393.     struct UFB * ufb;
  1394.  
  1395.     ENTER();
  1396.  
  1397.     initialize_libraries();
  1398.  
  1399.     ufb = chkufb(socketfd);
  1400.     if(ufb == NULL)
  1401.     {
  1402.         errno = EIO;
  1403.         goto out;
  1404.     }
  1405.  
  1406.     fh = (struct FileHandle *)BADDR(ufb->ufbfh);
  1407.     if(fh->fh_Type != &magic_port)
  1408.     {
  1409.         errno = EBADF;
  1410.         goto out;
  1411.     }
  1412.  
  1413.     socket_lock = DoPkt(&magic_port,ACTION_COPY_DIR_SOCKET,fh->fh_Arg1,    0,0,0,0);
  1414.     if(socket_lock == ZERO)
  1415.     {
  1416.         errno = EIO;
  1417.         goto out;
  1418.     }
  1419.  
  1420.     socket_handle = OpenFromLock(socket_lock);
  1421.     if(socket_handle == ZERO)
  1422.     {
  1423.         errno = EIO;
  1424.         goto out;
  1425.     }
  1426.  
  1427.     socket_lock = ZERO;
  1428.  
  1429.     fd = open("NIL:",O_RDWR,0777);
  1430.     if(fd < 0)
  1431.         goto out;
  1432.  
  1433.     ufb = chkufb(fd);
  1434.     if(ufb == NULL)
  1435.     {
  1436.         int error;
  1437.  
  1438.         error = errno;
  1439.  
  1440.         close(fd);
  1441.         fd = -1;
  1442.  
  1443.         errno = error;
  1444.         goto out;
  1445.     }
  1446.  
  1447.     Close(ufb->ufbfh);
  1448.     ufb->ufbfh = socket_handle;
  1449.  
  1450.     socket_handle = ZERO;
  1451.  
  1452.  out:
  1453.  
  1454.     if(fd < 0)
  1455.     {
  1456.         if(socket_handle != ZERO)
  1457.             Close(socket_handle);
  1458.  
  1459.         UnLock(socket_lock);
  1460.     }
  1461.  
  1462.     RETURN(fd);
  1463.     return(fd);
  1464. }
  1465.  
  1466. int
  1467. amiga_recv(int fd,void *buff,int nbytes,int flags)
  1468. {
  1469.     struct FileHandle * fh;
  1470.     struct UFB * ufb;
  1471.     int result = -1;
  1472.  
  1473.     ENTER();
  1474.  
  1475.     initialize_libraries();
  1476.  
  1477.     ufb = chkufb(fd);
  1478.     if(ufb == NULL)
  1479.     {
  1480.         errno = EIO;
  1481.         goto out;
  1482.     }
  1483.  
  1484.     fh = (struct FileHandle *)BADDR(ufb->ufbfh);
  1485.     if(fh->fh_Type != &magic_port)
  1486.     {
  1487.         errno = EBADF;
  1488.         goto out;
  1489.     }
  1490.  
  1491.     result = recv(fh->fh_Arg1,buff,nbytes,flags);
  1492.  
  1493.  out:
  1494.  
  1495.     RETURN(result);
  1496.     return(result);
  1497. }
  1498.  
  1499. int
  1500. amiga_send(int fd,void *buff,int nbytes,int flags)
  1501. {
  1502.     struct FileHandle * fh;
  1503.     struct UFB * ufb;
  1504.     int result = -1;
  1505.  
  1506.     ENTER();
  1507.  
  1508.     initialize_libraries();
  1509.  
  1510.     ufb = chkufb(fd);
  1511.     if(ufb == NULL)
  1512.     {
  1513.         errno = EIO;
  1514.         goto out;
  1515.     }
  1516.  
  1517.     fh = (struct FileHandle *)BADDR(ufb->ufbfh);
  1518.     if(fh->fh_Type != &magic_port)
  1519.     {
  1520.         errno = EBADF;
  1521.         goto out;
  1522.     }
  1523.  
  1524.     result = send(fh->fh_Arg1,buff,nbytes,flags);
  1525.  
  1526.  out:
  1527.  
  1528.     RETURN(result);
  1529.     return(result);
  1530. }
  1531.  
  1532. int
  1533. amiga_shutdown(int fd,int how)
  1534. {
  1535.     struct FileHandle * fh;
  1536.     struct UFB * ufb;
  1537.     int result = -1;
  1538.  
  1539.     ENTER();
  1540.  
  1541.     initialize_libraries();
  1542.  
  1543.     ufb = chkufb(fd);
  1544.     if(ufb == NULL)
  1545.     {
  1546.         errno = EIO;
  1547.         goto out;
  1548.     }
  1549.  
  1550.     fh = (struct FileHandle *)BADDR(ufb->ufbfh);
  1551.     if(fh->fh_Type != &magic_port)
  1552.     {
  1553.         errno = EBADF;
  1554.         goto out;
  1555.     }
  1556.  
  1557.     result = shutdown(fh->fh_Arg1,how);
  1558.  
  1559.  out:
  1560.  
  1561.     RETURN(result);
  1562.     return(result);
  1563. }
  1564.  
  1565. int
  1566. amiga_socket(int domain,int type,int protocol)
  1567. {
  1568.     BPTR socket_lock;
  1569.     BPTR socket_handle = ZERO;
  1570.     int fd = -1;
  1571.     struct UFB * ufb;
  1572.  
  1573.     ENTER();
  1574.  
  1575.     initialize_libraries();
  1576.  
  1577.     socket_lock = DoPkt(&magic_port,ACTION_LOCATE_SOCKET,domain,type,protocol,    0,0);
  1578.     if(socket_lock == ZERO)
  1579.     {
  1580.         errno = EIO;
  1581.         goto out;
  1582.     }
  1583.  
  1584.     socket_handle = OpenFromLock(socket_lock);
  1585.     if(socket_handle == ZERO)
  1586.     {
  1587.         errno = EIO;
  1588.         goto out;
  1589.     }
  1590.  
  1591.     socket_lock = ZERO;
  1592.  
  1593.     fd = open("NIL:",O_RDWR,0777);
  1594.     if(fd < 0)
  1595.         goto out;
  1596.  
  1597.     ufb = chkufb(fd);
  1598.     if(ufb == NULL)
  1599.     {
  1600.         int error;
  1601.  
  1602.         error = errno;
  1603.  
  1604.         close(fd);
  1605.         fd = -1;
  1606.  
  1607.         errno = error;
  1608.         goto out;
  1609.     }
  1610.  
  1611.     Close(ufb->ufbfh);
  1612.     ufb->ufbfh = socket_handle;
  1613.  
  1614.     socket_handle = ZERO;
  1615.  
  1616.  out:
  1617.  
  1618.     if(fd < 0)
  1619.     {
  1620.         if(socket_handle != ZERO)
  1621.             Close(socket_handle);
  1622.  
  1623.         UnLock(socket_lock);
  1624.     }
  1625.  
  1626.     RETURN(fd);
  1627.     return(fd);
  1628. }
  1629.  
  1630. /****************************************************************************/
  1631.  
  1632. int
  1633. amiga_piped_child(char ** argv,int * to_fd_ptr,int * from_fd_ptr)
  1634. {
  1635.     int len,total_len,quotes,escape,argc,i,j;
  1636.     char * s;
  1637.     char * arg;
  1638.     char * command;
  1639.     BPTR input = ZERO;
  1640.     BPTR output = ZERO;
  1641.     char in_name[40];
  1642.     char out_name[40];
  1643.     int result = -1;
  1644.  
  1645.     ENTER();
  1646.  
  1647.     argc = 0;
  1648.     total_len = 0;
  1649.     for (i = 0 ; argv[i] != NULL ; i++)
  1650.     {
  1651.         argc++;
  1652.         arg = argv[i];
  1653.         len = strlen(arg);
  1654.         quotes = 0;
  1655.  
  1656.         for(j = 0 ; j < len ; j++)
  1657.         {
  1658.             if(arg[j] == ' ' && quotes == 0)
  1659.                 quotes = 2;
  1660.             else if (arg[j] == '\"')
  1661.                 total_len++;
  1662.         }
  1663.  
  1664.         total_len += len + quotes + 1;
  1665.     }
  1666.  
  1667.     command = malloc(total_len+1);
  1668.     if(command == NULL)
  1669.     {
  1670.         errno = ENOMEM;
  1671.         return(-1);
  1672.     }
  1673.  
  1674.     s = command;
  1675.  
  1676.     for (i = 0 ; i < argc ; i++)
  1677.     {
  1678.         arg = argv[i];
  1679.         len = strlen(arg);
  1680.         quotes = escape = 0;
  1681.  
  1682.         for(j = 0 ; j < len ; j++)
  1683.         {
  1684.             if(arg[j] == ' ')
  1685.                 quotes = 1;
  1686.             else if (arg[j] == '\"')
  1687.                 escape = 1;
  1688.  
  1689.             if(quotes && escape)
  1690.                 break;
  1691.         }
  1692.  
  1693.         if(quotes)
  1694.             (*s++) = '\"';
  1695.  
  1696.         for(j = 0 ; j < len ; j++)
  1697.         {
  1698.             if(arg[j] == '\"')
  1699.                 (*s++) = '*';
  1700.  
  1701.             (*s++) = arg[j];
  1702.         }
  1703.  
  1704.         if(quotes)
  1705.             (*s++) = '\"';
  1706.  
  1707.         if(i < argc-1)
  1708.             (*s++) = ' ';
  1709.     }
  1710.  
  1711.     (*s) = '\0';
  1712.  
  1713.     SHOWSTRING(command);
  1714.  
  1715.     sprintf(in_name,"PIPE:in_%08x.%08x",FindTask(NULL),time(NULL));
  1716.     sprintf(out_name,"PIPE:out_%08x.%08x",FindTask(NULL),time(NULL));
  1717.  
  1718.     input = Open(in_name,MODE_OLDFILE);
  1719.     output = Open(out_name,MODE_NEWFILE);
  1720.     if(input != ZERO && output != ZERO)
  1721.     {
  1722.         LONG res;
  1723.  
  1724.         res = SystemTags(command,
  1725.             SYS_Input,        input,
  1726.             SYS_Output,        output,
  1727.             SYS_Asynch,        TRUE,
  1728.             SYS_UserShell,    TRUE,
  1729.         TAG_END);
  1730.  
  1731.         switch(res)
  1732.         {
  1733.             case 0:
  1734.                 (*to_fd_ptr) = open(in_name,O_WRONLY,0777);
  1735.                 if((*to_fd_ptr) == -1)
  1736.                     break;
  1737.  
  1738.                 (*from_fd_ptr) = open(out_name,O_RDONLY,0777);
  1739.                 if((*from_fd_ptr) == -1)
  1740.                     break;
  1741.  
  1742.                 result = 0;
  1743.                 break;
  1744.  
  1745.             case -1:
  1746.                 errno = ENOMEM;
  1747.                 Close(input);
  1748.                 Close(output);
  1749.                 break;
  1750.  
  1751.             default:
  1752.                 errno = EIO;
  1753.                 break;
  1754.         }
  1755.     }
  1756.     else
  1757.     {
  1758.         if(input != ZERO)
  1759.             Close(input);
  1760.  
  1761.         if(output != ZERO)
  1762.             Close(output);
  1763.  
  1764.         errno = EIO;
  1765.     }
  1766.  
  1767.     RETURN(result);
  1768.     return(result);
  1769. }
  1770.  
  1771. /****************************************************************************/
  1772.  
  1773. int
  1774. amiga_isabsolute(char *filename)
  1775. {
  1776.     int result = 0;
  1777.     int i;
  1778.  
  1779.     ENTER();
  1780.  
  1781.     SHOWSTRING(filename);
  1782.  
  1783.     for(i = 0 ; i < strlen(filename) ; i++)
  1784.     {
  1785.         if(filename[i] == ':')
  1786.         {
  1787.             result = 1;
  1788.             break;
  1789.         }
  1790.     }
  1791.  
  1792.     RETURN(result);
  1793.     return(result);
  1794. }
  1795.  
  1796. /****************************************************************************/
  1797.  
  1798. char *
  1799. amiga_last_component(char *path)
  1800. {
  1801.     char * result;
  1802.  
  1803.     ENTER();
  1804.  
  1805.     SHOWSTRING(path);
  1806.  
  1807.     result = FilePart(path);
  1808.  
  1809.     RETURN(result);
  1810.     return(result);
  1811. }
  1812.  
  1813. /****************************************************************************/
  1814.  
  1815. static int
  1816. recursive_unlink_file_dir(char *f)
  1817. {
  1818.     D_S(struct FileInfoBlock,fib);
  1819.     BPTR lock;
  1820.     int res = 0;
  1821.  
  1822.     lock = Lock(f,SHARED_LOCK);
  1823.     if(lock != ZERO)
  1824.     {
  1825.         if(Examine(lock,fib))
  1826.         {
  1827.             if(FIB_IS_DRAWER(fib))
  1828.             {
  1829.                 char name[110];
  1830.  
  1831.                 name[0] = '\0';
  1832.  
  1833.                 while(ExNext(lock,fib))
  1834.                 {
  1835.                     if(SetSignal(0,0) & SIGBREAKF_CTRL_C)
  1836.                     {
  1837.                         res = -1;
  1838.                         break;
  1839.                     }
  1840.  
  1841.                     if(name[0] != '\0')
  1842.                     {
  1843.                         if(DeleteFile(name))
  1844.                         {
  1845.                             res = -1;
  1846.                             break;
  1847.                         }
  1848.  
  1849.                         name[0] = '\0';
  1850.                     }
  1851.  
  1852.                     if(FIB_IS_DRAWER(fib))
  1853.                     {
  1854.                         BPTR old_dir;
  1855.  
  1856.                         old_dir = CurrentDir(lock);
  1857.                         res = recursive_unlink_file_dir(fib->fib_FileName);
  1858.                         CurrentDir(old_dir);
  1859.  
  1860.                         if(res != 0)
  1861.                             break;
  1862.                     }
  1863.  
  1864.                     strcpy(name,fib->fib_FileName);
  1865.                 }
  1866.  
  1867.                 if(res == 0 && name[0] != '\0')
  1868.                 {
  1869.                     if(CANNOT DeleteFile(name))
  1870.                         res = -1;
  1871.                 }
  1872.             }
  1873.  
  1874.             UnLock(lock);
  1875.  
  1876.             if(res == 0)
  1877.             {
  1878.                 if(CANNOT DeleteFile(f))
  1879.                     res = -1;
  1880.             }
  1881.         }
  1882.         else
  1883.         {
  1884.             UnLock(lock);
  1885.         }
  1886.     }
  1887.  
  1888.     return(res);
  1889. }
  1890.  
  1891. int
  1892. amiga_unlink_file_dir(char * f)
  1893. {
  1894.     int res;
  1895.  
  1896.     ENTER();
  1897.  
  1898.     correct_name(&f);
  1899.  
  1900.     SHOWSTRING(f);
  1901.  
  1902.     res = recursive_unlink_file_dir(f);
  1903.  
  1904.     RETURN(res);
  1905.     return(res);
  1906. }
  1907.  
  1908. /****************************************************************************/
  1909.  
  1910. int
  1911. amiga_fncmp(char *n1,char *n2)
  1912. {
  1913.     int result;
  1914.  
  1915.     ENTER();
  1916.  
  1917.     SHOWSTRING(n1);
  1918.     SHOWSTRING(n2);
  1919.  
  1920.     result = Stricmp(n1,n2);
  1921.  
  1922.     RETURN(result);
  1923.     return(result);
  1924. }
  1925.  
  1926. /****************************************************************************/
  1927.  
  1928. void
  1929. amiga_fnfold(char *name)
  1930. {
  1931.     int c;
  1932.  
  1933.     while((c = (*(unsigned char *)name)) != '\0')
  1934.         (*name++) = ToLower(c);
  1935. }
  1936.  
  1937. /****************************************************************************/
  1938.  
  1939. int
  1940. amiga_fold_fn_char(int c)
  1941. {
  1942.     int result;
  1943.  
  1944.     result = ToLower(c);
  1945.  
  1946.     return(result);
  1947. }
  1948.  
  1949. /****************************************************************************/
  1950.  
  1951. typedef struct name_node
  1952. {
  1953.     struct name_node *    nn_next;
  1954.     char *                nn_name;
  1955.     BOOL                nn_wild;
  1956. } name_node_t;
  1957.  
  1958. static int
  1959. compare(char **a,char **b)
  1960. {
  1961.     return(Stricmp(*a,*b));
  1962. }
  1963.  
  1964. void
  1965. amiga_expand_wild(int argc,char ** argv,int * _argc,char *** _argv)
  1966. {
  1967.     struct AnchorPath * anchor;
  1968.     name_node_t * root;
  1969.     name_node_t * node;
  1970.     LONG name_plus;
  1971.     LONG name_total;
  1972.     LONG i;
  1973.  
  1974.     ENTER();
  1975.  
  1976.     anchor        = (struct AnchorPath *)xmalloc(sizeof(*anchor) + 2 * MAX_FILENAME_LEN);
  1977.     root        = NULL;
  1978.     name_plus    = 0;
  1979.     name_total    = 0;
  1980.  
  1981.     memset(anchor,0,sizeof(*anchor));
  1982.  
  1983.     anchor->ap_Strlen        = MAX_FILENAME_LEN;
  1984.     anchor->ap_BreakBits    = SIGBREAKF_CTRL_C;
  1985.  
  1986.     for(i = 0 ; i < argc ; i++)
  1987.     {
  1988.         if(i > 0 && ParsePatternNoCase(argv[i],anchor->ap_Buf,2 * MAX_FILENAME_LEN) > 0)
  1989.         {
  1990.             LONG result;
  1991.  
  1992.             result = MatchFirst(argv[i],anchor);
  1993.  
  1994.             while(result == 0)
  1995.             {
  1996.                 node = (name_node_t *)malloc(sizeof(*node) + strlen(anchor->ap_Buf) + 1);
  1997.                 if(node == NULL)
  1998.                 {
  1999.                     char buf[80];
  2000.  
  2001.                     MatchEnd(anchor);
  2002.  
  2003.                     sprintf(buf,"out of memory; can not allocate %lu bytes",
  2004.                         (unsigned long)(sizeof(*node) + strlen(anchor->ap_Buf) + 1));
  2005.  
  2006.                     error(1,0,buf);
  2007.                 }
  2008.  
  2009.                 node->nn_name = (char *)(node + 1);
  2010.                 node->nn_next = root;
  2011.                 node->nn_wild = TRUE;
  2012.  
  2013.                 strcpy(node->nn_name,anchor->ap_Buf);
  2014.  
  2015.                 root = node;
  2016.  
  2017.                 name_plus++;
  2018.                 name_total++;
  2019.  
  2020.                 result = MatchNext(anchor);
  2021.             }
  2022.  
  2023.             MatchEnd(anchor);
  2024.         }
  2025.         else
  2026.         {
  2027.             node = (name_node_t *)xmalloc(sizeof(*node));
  2028.  
  2029.             node->nn_name = argv[i];
  2030.             node->nn_next = root;
  2031.             node->nn_wild = FALSE;
  2032.  
  2033.             root = node;
  2034.  
  2035.             name_total++;
  2036.         }
  2037.     }
  2038.  
  2039.     if(name_plus > 0)
  2040.     {
  2041.         char ** last_wild;
  2042.         char ** index;
  2043.  
  2044.         index = (char **)xmalloc(sizeof(char *) * (name_total + 1));
  2045.  
  2046.         (*_argc) = name_total;
  2047.         (*_argv) = index;
  2048.  
  2049.         index = &(index[name_total]);
  2050.  
  2051.         (*index--) = NULL;
  2052.  
  2053.         node        = root;
  2054.         last_wild    = NULL;
  2055.  
  2056.         while(node != NULL)
  2057.         {
  2058.             if(node->nn_wild)
  2059.             {
  2060.                 if(last_wild == NULL)
  2061.                     last_wild = index;
  2062.             }
  2063.             else
  2064.             {
  2065.                 if(last_wild)
  2066.                 {
  2067.                     if((ULONG)last_wild - (ULONG)index > sizeof(char **))
  2068.                         qsort(index + 1,((ULONG)last_wild - (ULONG)index) / sizeof(char **),sizeof(char *),compare);
  2069.  
  2070.                     last_wild = NULL;
  2071.                 }
  2072.             }
  2073.  
  2074.             (*index--) = node->nn_name;
  2075.  
  2076.             node = node->nn_next;
  2077.         }
  2078.     }
  2079.     else
  2080.     {
  2081.         name_node_t * next;
  2082.  
  2083.         node = root;
  2084.  
  2085.         while(node != NULL)
  2086.         {
  2087.             next = node->nn_next;
  2088.  
  2089.             free(node);
  2090.  
  2091.             node = next;
  2092.         }
  2093.     }
  2094.  
  2095.     free(anchor);
  2096.  
  2097.     LEAVE();
  2098. }
  2099.  
  2100. /****************************************************************************/
  2101.  
  2102. static void
  2103. convert_fileinfo_to_stat(struct FileInfoBlock * fib,struct stat * st)
  2104. {
  2105.     ULONG flags;
  2106.     int mode;
  2107.     long time;
  2108.  
  2109.     /* This routine converts the contents of a FileInfoBlock
  2110.      * into information to fill a Unix-like stat data structure
  2111.      * with.
  2112.      */
  2113.     flags = fib->fib_Protection ^ (FIBF_READ|FIBF_WRITE|FIBF_EXECUTE|FIBF_DELETE);
  2114.  
  2115.     if(FIB_IS_DRAWER(fib))
  2116.         mode = S_IFDIR;
  2117.     else
  2118.         mode = S_IFREG;
  2119.  
  2120.     if(FLAG_IS_SET(flags,FIBF_READ))
  2121.         SET_FLAG(mode,S_IRUSR);
  2122.  
  2123.     if(FLAG_IS_SET(flags,FIBF_WRITE) && FLAG_IS_SET(flags,FIBF_DELETE))
  2124.         SET_FLAG(mode,S_IWUSR);
  2125.  
  2126.     if(FLAG_IS_SET(flags,FIBF_EXECUTE))
  2127.         SET_FLAG(mode,S_IXUSR);
  2128.  
  2129.  
  2130.     if(FLAG_IS_SET(flags,FIBF_GRP_READ))
  2131.         SET_FLAG(mode,S_IRGRP);
  2132.  
  2133.     if(FLAG_IS_SET(flags,FIBF_GRP_WRITE) && FLAG_IS_SET(flags,FIBF_GRP_DELETE))
  2134.         SET_FLAG(mode,S_IWGRP);
  2135.  
  2136.     if(FLAG_IS_SET(flags,FIBF_GRP_EXECUTE))
  2137.         SET_FLAG(mode,S_IXGRP);
  2138.  
  2139.  
  2140.     if(FLAG_IS_SET(flags,FIBF_OTR_READ))
  2141.         SET_FLAG(mode,S_IROTH);
  2142.  
  2143.     if(FLAG_IS_SET(flags,FIBF_OTR_WRITE) && FLAG_IS_SET(flags,FIBF_OTR_DELETE))
  2144.         SET_FLAG(mode,S_IWOTH);
  2145.  
  2146.     if(FLAG_IS_SET(flags,FIBF_OTR_EXECUTE))
  2147.         SET_FLAG(mode,S_IXOTH);
  2148.  
  2149.     time = fib->fib_Date.ds_Days * 24*60*60 +
  2150.           (fib->fib_Date.ds_Minute+60) * 60 +               /* jlangner +60 time fix */
  2151.           (fib->fib_Date.ds_Tick / TICKS_PER_SECOND);
  2152.  
  2153.     memset(st,0,sizeof(*st));
  2154.  
  2155.     st->st_mode        = mode;
  2156.     st->st_mtime    = UNIX_TIME_OFFSET + time + 60 * get_minutes_west();    /* translate from local time to UTC */
  2157.     st->st_atime    = st->st_mtime;
  2158.     st->st_ctime    = st->st_mtime;
  2159.  
  2160.     if(FIB_IS_FILE(fib))
  2161.     {
  2162.         st->st_nlink = 1;
  2163.         st->st_size  = fib->fib_Size;
  2164.     }
  2165.     else
  2166.     {
  2167.         st->st_nlink = 2;
  2168.     }
  2169. }
  2170.  
  2171. /****************************************************************************/
  2172.  
  2173. int
  2174. amiga_stat(char *name, struct stat *st)
  2175. {
  2176.     int result = -1;
  2177.     BPTR fileLock;
  2178.     int len;
  2179.  
  2180.     chkabort();
  2181.  
  2182.     correct_name(&name);
  2183.  
  2184.     len = strlen(name);
  2185.  
  2186.     fileLock = Lock((STRPTR)name,SHARED_LOCK);
  2187.     if(fileLock != ZERO)
  2188.     {
  2189.         D_S(struct FileInfoBlock,fib);
  2190.  
  2191.         if(Examine(fileLock,fib))
  2192.         {
  2193.             BPTR parentDir;
  2194.  
  2195.             /* Check if this is a root directory. */
  2196.             parentDir = ParentDir(fileLock);
  2197.             if(parentDir != ZERO)
  2198.             {
  2199.                 /* This is not the root directory. */
  2200.                 UnLock(parentDir);
  2201.             }
  2202.             else
  2203.             {
  2204.                 /* So this is a root directory. Make sure
  2205.                  * that we return proper protection bits for
  2206.                  * it, i.e. that the directory is always
  2207.                  * readable, writable, etc. This may be
  2208.                  * necessary since on the Amiga, root
  2209.                  * directories cannot have any protection
  2210.                  * bits set. Note that the "deletable"
  2211.                  * bits don't make much sense, but then
  2212.                  * these bits work together with the
  2213.                  * writable bits. The lowest four bits
  2214.                  * remain zero, which enables them all.
  2215.                  */
  2216.                 fib->fib_Protection = FIBF_OTR_READ |
  2217.                                       FIBF_OTR_WRITE |
  2218.                                       FIBF_OTR_EXECUTE |
  2219.                                       FIBF_OTR_DELETE |
  2220.                                       FIBF_GRP_READ |
  2221.                                       FIBF_GRP_WRITE |
  2222.                                       FIBF_GRP_EXECUTE |
  2223.                                       FIBF_GRP_DELETE;
  2224.             }
  2225.  
  2226.             convert_fileinfo_to_stat(fib,st);
  2227.  
  2228.             result = OK;
  2229.         }
  2230.         else
  2231.         {
  2232.             map_ioerr_to_errno();
  2233.         }
  2234.  
  2235.         UnLock(fileLock);
  2236.     }
  2237.     else
  2238.     {
  2239.         map_ioerr_to_errno();
  2240.     }
  2241.  
  2242.     return(result);
  2243. }
  2244.  
  2245. /****************************************************************************/
  2246.  
  2247. int
  2248. amiga_lstat(char *name, struct stat *statstruct)
  2249. {
  2250.     int result;
  2251.  
  2252.     result = amiga_stat(name,statstruct);
  2253.  
  2254.     return(result);
  2255. }
  2256.  
  2257. /****************************************************************************/
  2258.  
  2259. int
  2260. amiga_fstat(int fd,struct stat * st)
  2261. {
  2262.     struct UFB * ufb;
  2263.     int result = -1;
  2264.  
  2265.     chkabort();
  2266.  
  2267.     ufb = chkufb(fd);
  2268.     if(ufb != NULL)
  2269.     {
  2270.         D_S(struct FileInfoBlock,fib);
  2271.  
  2272.         if(ExamineFH(ufb->ufbfh,fib))
  2273.         {
  2274.             convert_fileinfo_to_stat(fib,st);
  2275.  
  2276.             result = OK;
  2277.         }
  2278.         else
  2279.         {
  2280.             map_ioerr_to_errno();
  2281.         }
  2282.     }
  2283.  
  2284.     return(result);
  2285. }
  2286.  
  2287. /******************************************************************************/
  2288.  
  2289. char *amiga_inet_ntoa(struct in_addr iaddr)
  2290. {
  2291.     return(Inet_NtoA(iaddr.s_addr));
  2292. }
  2293.  
  2294. /******************************************************************************/
  2295.  
  2296. int
  2297. amiga_chmod(char *name,int mode)
  2298. {
  2299.     int result = OK;
  2300.     ULONG flags = 0;
  2301.  
  2302.     chkabort();
  2303.  
  2304.     /* Convert the file access modes into
  2305.      * Amiga typical protection bits.
  2306.      */
  2307.     if(FLAG_IS_SET(mode,S_IRUSR))
  2308.         SET_FLAG(flags,FIBF_READ);
  2309.  
  2310.     if(FLAG_IS_SET(mode,S_IWUSR))
  2311.     {
  2312.         SET_FLAG(flags,FIBF_WRITE);
  2313.         SET_FLAG(flags,FIBF_DELETE);
  2314.     }
  2315.  
  2316.     if(FLAG_IS_SET(mode,S_IXUSR))
  2317.         SET_FLAG(flags,FIBF_EXECUTE);
  2318.  
  2319.  
  2320.     if(FLAG_IS_SET(mode,S_IRGRP))
  2321.         SET_FLAG(flags,FIBF_GRP_READ);
  2322.  
  2323.     if(FLAG_IS_SET(mode,S_IWGRP))
  2324.     {
  2325.         SET_FLAG(flags,FIBF_GRP_WRITE);
  2326.         SET_FLAG(flags,FIBF_GRP_DELETE);
  2327.     }
  2328.  
  2329.     if(FLAG_IS_SET(mode,S_IXGRP))
  2330.         SET_FLAG(flags,FIBF_GRP_EXECUTE);
  2331.  
  2332.  
  2333.     if(FLAG_IS_SET(mode,S_IROTH))
  2334.         SET_FLAG(flags,FIBF_OTR_READ);
  2335.  
  2336.     if(FLAG_IS_SET(mode,S_IWOTH))
  2337.     {
  2338.         SET_FLAG(flags,FIBF_OTR_WRITE);
  2339.         SET_FLAG(flags,FIBF_OTR_DELETE);
  2340.     }
  2341.  
  2342.     if(FLAG_IS_SET(mode,S_IXOTH))
  2343.         SET_FLAG(flags,FIBF_OTR_EXECUTE);
  2344.  
  2345.     flags ^= (FIBF_READ|FIBF_WRITE|FIBF_EXECUTE|FIBF_DELETE);
  2346.  
  2347.     correct_name(&name);
  2348.  
  2349.     if(CANNOT SetProtection(name,flags))
  2350.     {
  2351.         LONG error;
  2352.  
  2353.         error = IoErr();
  2354.         if(error != ERROR_OBJECT_IN_USE)
  2355.         {
  2356.             SetIoErr(error);
  2357.  
  2358.             map_ioerr_to_errno();
  2359.  
  2360.             result = -1;
  2361.         }
  2362.     }
  2363.  
  2364.     return(result);
  2365. }
  2366.  
  2367. /****************************************************************************/
  2368.  
  2369. int
  2370. amiga_access(char *name,int modes)
  2371. {
  2372.     int result;
  2373.  
  2374.     ENTER();
  2375.  
  2376.     correct_name(&name);
  2377.  
  2378.     SHOWSTRING(name);
  2379.     SHOWVALUE(modes);
  2380.  
  2381.     /* We ignore the 'x' bit since it doesn't matter
  2382.      * on the Amiga.
  2383.      */
  2384.     result = access(name,modes & ~X_OK);
  2385.  
  2386.     RETURN(result);
  2387.     return(result);
  2388. }
  2389.  
  2390. /****************************************************************************/
  2391.  
  2392. static BPTR home_dir;
  2393.  
  2394. static void
  2395. restore_home_dir(void)
  2396. {
  2397.     if(home_dir != ZERO)
  2398.     {
  2399.         UnLock(CurrentDir(home_dir));
  2400.         home_dir = ZERO;
  2401.     }
  2402. }
  2403.  
  2404. DEFAULT_DESTRUCTOR(restore_home_dir)
  2405. {
  2406.     restore_home_dir();
  2407. }
  2408.  
  2409. /****************************************************************************/
  2410.  
  2411. int
  2412. amiga_chdir(char *path)
  2413. {
  2414.     int result;
  2415.  
  2416.     ENTER();
  2417.  
  2418.     if(home_dir == ZERO)
  2419.     {
  2420.         BPTR old_dir;
  2421.  
  2422.         /* This is tricky at best. chdir() will change the
  2423.          * current directory of this process and unlock the
  2424.          * previously active current directory lock. However,
  2425.          * the current directory lock with which this program
  2426.          * was launched *must not* be unlocked; the same lock
  2427.          * the program was launched with must be the one the
  2428.          * program exits with. This is what we are trying to
  2429.          * achieve here.
  2430.          */
  2431.         old_dir = Lock("",SHARED_LOCK);
  2432.         if(old_dir == ZERO)
  2433.         {
  2434.             errno = EIO;
  2435.             result = -1;
  2436.             goto out;
  2437.         }
  2438.  
  2439.         home_dir = CurrentDir(old_dir);
  2440.     }
  2441.  
  2442.     correct_name(&path);
  2443.  
  2444.     SHOWSTRING(path);
  2445.  
  2446.     result = chdir(path);
  2447.  
  2448.  out:
  2449.  
  2450.     RETURN(result);
  2451.     return(result);
  2452. }
  2453.  
  2454. int
  2455. amiga_creat(char *name,int prot)
  2456. {
  2457.     int result;
  2458.  
  2459.     ENTER();
  2460.  
  2461.     correct_name(&name);
  2462.  
  2463.     SHOWSTRING(name);
  2464.     SHOWVALUE(prot);
  2465.  
  2466.     result = creat(name,prot);
  2467.  
  2468.     RETURN(result);
  2469.     return(result);
  2470. }
  2471.  
  2472. FILE *
  2473. amiga_fopen(char *name,const char *modes)
  2474. {
  2475.     FILE * result;
  2476.  
  2477.     ENTER();
  2478.  
  2479.     correct_name(&name);
  2480.  
  2481.     SHOWSTRING(name);
  2482.     SHOWSTRING(modes);
  2483.  
  2484.     result = fopen(name,modes);
  2485.  
  2486.     RETURN(result);
  2487.     return(result);
  2488. }
  2489.  
  2490. int
  2491. amiga_open(char *name,int mode,int prot)
  2492. {
  2493.     int result;
  2494.  
  2495.     ENTER();
  2496.  
  2497.     correct_name(&name);
  2498.  
  2499.     SHOWSTRING(name);
  2500.     SHOWVALUE(mode);
  2501.  
  2502.     result = open(name,mode);
  2503.  
  2504.     RETURN(result);
  2505.     return(result);
  2506. }
  2507.  
  2508. void *
  2509. amiga_opendir(char *dir_name)
  2510. {
  2511.     void * result;
  2512.  
  2513.     ENTER();
  2514.  
  2515.     correct_name(&dir_name);
  2516.  
  2517.     SHOWSTRING(dir_name);
  2518.  
  2519.     result = opendir(dir_name);
  2520.  
  2521.     RETURN(result);
  2522.     return(result);
  2523. }
  2524.  
  2525. int
  2526. amiga_rename(char *old,char *new)
  2527. {
  2528.     int result;
  2529.  
  2530.     ENTER();
  2531.  
  2532.     correct_name(&old);
  2533.     correct_name(&new);
  2534.  
  2535.     SHOWSTRING(old);
  2536.     SHOWSTRING(new);
  2537.  
  2538.     result = rename(old,new);
  2539.     if(result == -1 && errno == EEXIST)
  2540.     {
  2541.         unlink(new);
  2542.         result = rename(old,new);
  2543.     }
  2544.  
  2545.     RETURN(result);
  2546.     return(result);
  2547. }
  2548.  
  2549. int
  2550. amiga_rmdir(char *name)
  2551. {
  2552.     int result;
  2553.  
  2554.     ENTER();
  2555.  
  2556.     correct_name(&name);
  2557.  
  2558.     SHOWSTRING(name);
  2559.  
  2560.     result = rmdir(name);
  2561.  
  2562.     RETURN(result);
  2563.     return(result);
  2564. }
  2565.  
  2566. int
  2567. amiga_unlink(char *name)
  2568. {
  2569.     int result;
  2570.  
  2571.     ENTER();
  2572.  
  2573.     correct_name(&name);
  2574.  
  2575.     SHOWSTRING(name);
  2576.  
  2577.     result = unlink(name);
  2578.  
  2579.     RETURN(result);
  2580.     return(result);
  2581. }
  2582.  
  2583. /****************************************************************************/
  2584.  
  2585. char *
  2586. amiga_cvs_temp_name(void)
  2587. {
  2588.     extern char *Tmpdir;
  2589.     char *value;
  2590.     char *retval;
  2591.     int max_len;
  2592.     int len;
  2593.  
  2594.     ENTER();
  2595.  
  2596.     max_len = strlen (Tmpdir) + 40;
  2597.  
  2598.     value = xmalloc (max_len);
  2599.  
  2600.     strcpy(value,Tmpdir);
  2601.     len = strlen(value);
  2602.     while(len > 0 && value[len-1] == '/')
  2603.         value[--len] = '\0';
  2604.  
  2605.     AddPart(value,"cvsXXXXXX",max_len);
  2606.  
  2607.     retval = mktemp (value);
  2608.  
  2609.     if (retval == NULL)
  2610.         error (1, errno, "cannot generate temporary filename");
  2611.  
  2612.     SHOWSTRING(value);
  2613.  
  2614.     RETURN(value);
  2615.     return(value);
  2616. }
  2617.  
  2618. /****************************************************************************/
  2619.  
  2620. static int amiga_rcmd(char **remote_hostname, int remote_port,char *local_user, char *remote_user,char *command)
  2621. {
  2622.   struct hostent *remote_hp;
  2623.   struct hostent *local_hp;
  2624.   struct sockaddr_in remote_isa;
  2625.   struct sockaddr_in local_isa;
  2626.   char local_hostname[80];
  2627.   char ch;
  2628.   int s;
  2629.   int local_port;
  2630.   int rs;
  2631.  
  2632.   remote_hp = amiga_gethostbyname(*remote_hostname);
  2633.   if(!remote_hp)
  2634.     {
  2635.     perror("couldn't get remote host address");
  2636.     exit(1);
  2637.     }
  2638.  
  2639.   /* Copy remote IP address into socket address structure */
  2640.   memset(&remote_isa,0,sizeof(remote_isa));
  2641.   remote_isa.sin_family = AF_INET;
  2642.   remote_isa.sin_port = htons(remote_port);
  2643.   memcpy(&remote_isa.sin_addr, remote_hp->h_addr, sizeof(remote_isa.sin_addr));
  2644.  
  2645.   amiga_gethostname(local_hostname, 80);
  2646.   local_hp = amiga_gethostbyname(local_hostname);
  2647.   if(!local_hp)
  2648.     {
  2649.     perror("couldn't get local host address");
  2650.     exit(1);
  2651.     }
  2652.  
  2653.   /* Copy local IP address into socket address structure */
  2654.   memset(&local_isa,0,sizeof(local_isa));
  2655.   local_isa.sin_family = AF_INET;
  2656.   memcpy(&local_isa.sin_addr, local_hp->h_addr, sizeof(local_isa.sin_addr));
  2657.  
  2658.   /* Create the local socket */
  2659.   s = amiga_socket(AF_INET, SOCK_STREAM, 0);
  2660.   if(s < 0)
  2661.     {
  2662.     perror("socket failed\n");
  2663.     exit(1);
  2664.     }
  2665.  
  2666.   /* Bind local socket with a port from IPPORT_RESERVED/2 to IPPORT_RESERVED - 1
  2667.      this requires the OPER privilege under VMS -- to allow communication with
  2668.      a stock rshd under UNIX */
  2669.  
  2670.   for(local_port = IPPORT_RESERVED - 1; local_port >= IPPORT_RESERVED/2; local_port--)
  2671.     {
  2672.     local_isa.sin_port = htons(local_port);
  2673.     rs = amiga_bind(s, (struct sockaddr *)&local_isa, sizeof(local_isa));
  2674.     if(rs == 0)
  2675.       break;
  2676.     }
  2677.  
  2678.   /* Bind local socket to an unprivileged port.  A normal rshd will drop the
  2679.      connection; you must be running a patched rshd invoked through inetd for
  2680.      this connection method to work */
  2681.  
  2682.   if (rs != 0)
  2683.     for(local_port = IPPORT_USERRESERVED - 1;
  2684.         local_port > IPPORT_RESERVED;
  2685.         local_port--)
  2686.       {
  2687.       local_isa.sin_port = htons(local_port);
  2688.       rs = amiga_bind(s, (struct sockaddr *)&local_isa, sizeof(local_isa));
  2689.       if(rs == 0)
  2690.         break;
  2691.       }
  2692.  
  2693.   rs = amiga_connect(s, (struct sockaddr *) &remote_isa, sizeof(remote_isa));
  2694.   if(rs == -1)
  2695.     {
  2696.     fprintf(stderr, "connect: errno = %d\n", errno);
  2697.     close(s);
  2698.     exit(2);
  2699.     }
  2700.  
  2701.   /* Now supply authentication information */
  2702.  
  2703.   /* Auxiliary port number for error messages, we don't use it */
  2704.   write(s, "0\0", 2);
  2705.  
  2706.   /* Who are we */
  2707.   write(s, local_user, strlen(local_user) + 1);
  2708.  
  2709.   /* Who do we want to be */
  2710.   write(s, remote_user, strlen(remote_user) + 1);
  2711.  
  2712.   /* What do we want to run */
  2713.   write(s, command, strlen(command) + 1);
  2714.  
  2715.   /* NUL is sent back to us if information is acceptable */
  2716.   read(s, &ch, 1);
  2717.   if(ch != '\0')
  2718.     {
  2719.     errno = EPERM;
  2720.     return -1;
  2721.     }
  2722.  
  2723.   return s;
  2724. }
  2725.  
  2726. static char *cvs_server;
  2727. static char *command;
  2728.  
  2729. extern int trace;
  2730.  
  2731. void
  2732. amiga_start_server (int *tofd, int *fromfd,char *client_user, char *server_user,char *server_host, char *server_cvsroot)
  2733. {
  2734.   int fd, port;
  2735.   char *portenv;
  2736.   struct servent *sptr;
  2737.  
  2738.   if (! (cvs_server = getenv ("CVS_SERVER")))
  2739.       cvs_server = "cvs";
  2740.   command = xmalloc (strlen (cvs_server)
  2741.              + strlen (server_cvsroot)
  2742.              + 50);
  2743.   sprintf(command, "%s server", cvs_server);
  2744.  
  2745.   portenv = getenv("CVS_RCMD_PORT");
  2746.   if (portenv)
  2747.       port = atoi(portenv);
  2748.   else if ((sptr = amiga_getservbyname("shell", "tcp")) != NULL)
  2749.       port = sptr->s_port;
  2750.   else
  2751.       port = 514; /* shell/tcp */
  2752.  
  2753.   if(trace)
  2754.     {
  2755.     fprintf(stderr, "amiga_start_server(): connecting to %s:%d\n",
  2756.             server_host, port);
  2757.     fprintf(stderr, "local_user = %s, remote_user = %s, CVSROOT = %s\n",
  2758.             client_user, (server_user ? server_user : client_user),
  2759.             server_cvsroot);
  2760.     }
  2761.  
  2762.   fd = amiga_rcmd(&server_host, port,
  2763.             client_user,
  2764.             (server_user ? server_user : client_user),
  2765.             command);
  2766.  
  2767.   if (fd < 0)
  2768.      error (1, errno, "cannot start server via rcmd()");
  2769.  
  2770.   (*tofd) = fd;
  2771.   (*fromfd) = fd;
  2772.  
  2773.   free (command);
  2774. }
  2775.  
  2776. void
  2777. amiga_shutdown_server (int fd)
  2778. {
  2779.     /* FIXME: shutdown on files seems to have no bad effects */
  2780.     if (amiga_shutdown (fd, 2) < 0 && errno != ENOTSOCK)
  2781.         error (1, 0, "couldn't shutdown server connection");
  2782.     if (close (fd) < 0)
  2783.         error (1, 0, "couldn't close server connection");
  2784. }
  2785.  
  2786. /****************************************************************************/
  2787.  
  2788. void
  2789. amiga_system_initialize(int * _argc,char *** _argv)
  2790. {
  2791.     amiga_expand_wild((*_argc),(*_argv),_argc,_argv);
  2792. }
  2793.